{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sqlalchemy import create_engine\n",
    "from sqlalchemy.orm import Session\n",
    "from oso import Oso\n",
    "from sqlalchemy_oso.hooks import authorized_sessionmaker\n",
    "from sqlalchemy_oso.auth import register_models\n",
    "from sqlalchemy_example.models import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "oso = Oso()\n",
    "register_models(oso, Model)\n",
    "oso.load_file(\"sqlalchemy_example/policy.polar\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "user = User(username='user')\n",
    "manager = User(username='manager', manages=[user])\n",
    "                                                             \n",
    "public_user_post = Post(contents='public_user_post',\n",
    "                        access_level='public',\n",
    "                        created_by=user)\n",
    "private_user_post = Post(contents='private_user_post',\n",
    "                        access_level='private',\n",
    "                        created_by=user)\n",
    "private_manager_post = Post(contents='private_manager_post',\n",
    "                            access_level='private',\n",
    "                            created_by=manager)\n",
    "public_manager_post = Post(contents='public_manager_post',\n",
    "                           access_level='public',\n",
    "                           created_by=manager)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "engine = create_engine('sqlite:///:memory:')\n",
    "Model.metadata.create_all(engine)\n",
    "session = Session(bind=engine)\n",
    "session.add_all([user, manager, public_user_post, private_user_post, private_manager_post, public_manager_post])\n",
    "session.commit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "AuthorizedSession = authorized_sessionmaker(bind=engine,\n",
    "                                            get_oso=lambda: oso,\n",
    "                                            get_user=lambda: user,\n",
    "                                            get_action=lambda: \"read\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "session = AuthorizedSession()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we've setup some test data, let's use **oso** to authorize `Post`s that `User(username=\"user\")` can see."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "posts = session.query(Post).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['public_user_post', 'private_user_post', 'public_manager_post']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[p.contents for p in posts]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`user` can see their own public and private posts, and other public posts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "AuthorizedSession = authorized_sessionmaker(bind=engine,\n",
    "                                            get_oso=lambda: oso,\n",
    "                                            get_user=lambda: manager,\n",
    "                                            get_action=lambda: \"read\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "session = AuthorizedSession()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we'll authorize access to `manager`'s `Post`s."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "posts = session.query(Post).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['public_user_post',\n",
       " 'private_user_post',\n",
       " 'private_manager_post',\n",
       " 'public_manager_post']"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[p.contents for p in posts]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We got 4 posts this time, the manager's public and private posts, other user's private posts **and** private posts of users that the `manager` user manages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'user'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "manager.manages[0].username"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "More complex queries can be authorized as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "AuthorizedSession = authorized_sessionmaker(bind=engine,\n",
    "                                            get_oso=lambda: oso,\n",
    "                                            get_user=lambda: user,\n",
    "                                            get_action=lambda: \"read\")\n",
    "session = AuthorizedSession()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('public_user_post'), ('private_user_post'), ('public_manager_post')]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "session.query(Post.contents).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('public_user_post', 'user'),\n",
       " ('public_user_post', 'manager'),\n",
       " ('private_user_post', 'user'),\n",
       " ('private_user_post', 'manager'),\n",
       " ('public_manager_post', 'user'),\n",
       " ('public_manager_post', 'manager')]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "session.query(Post.contents, User.username).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('public_user_post', 'user'),\n",
       " ('private_user_post', 'user'),\n",
       " ('public_manager_post', 'manager')]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "session.query(Post.contents, User.username).join(User).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
